import { Vector3 } from "stl-typescript";
import {
  offsetByVec3,
  createPolyData,
  createCellData,
  createPoints,
  createPolyDataNormals,
} from "cax-base";

/**
 * @interface TCell
 * @param cellId cell Id 格宇的角标id
 * @param partId part Id
 * @param partType 单元类型
 * @param componentsNumber 单元节点数
 * @param nodes 网格节点坐标，每个节点的 id + xyz 坐标
 */
export interface TCell {
  cellId: number;
  partId: number;
  partType: number;
  componentsNumber: number;
  nodes: number[][];
}

/**
 * @class TFace 网格单元集合
 * @param data 网格单元数据
 * @function parseForGy(data: any) 解析为格宇数据
 * @function getPolyData() 构建几何结构
 * @function containsCellId(cellId: number) 判断单元是否在网格单元集合中
 * @function getGyCellId(cellId: number) 获取单元在格宇中的单元 id
 * @function getCellPos(cellId: number) 获取单元中心点坐标
 * @function offsetForBetterView() 偏置一个距离来更好的显示
 */
export class TFace {
  data: TCell[] = [];
  polyData = createPolyData();
  points = createPoints();
  cells = createCellData();

  // * 构建几何结构
  createPointData() {
    const TMP_arr = [];

    for (let i = 0; i < this.data.length; i++) {
      // !! 一组数据有几个点
      const num = this.data[i].componentsNumber;
      for (let n = 0; n < num; n++) {
        TMP_arr.push(
          this.data[i].nodes[n][1],
          this.data[i].nodes[n][2],
          this.data[i].nodes[n][3]
        );
      }
    }
    this.points.setData(TMP_arr, 3);
  }

  createCellData() {
    let offset = 0;
    for (let i = 0; i < this.data.length; i++) {
      const count = this.data[i].componentsNumber;
      const cellPointIds = [];
      for (let j = 0; j < count; j++) {
        cellPointIds.push(offset + j);
      }
      offset += count;
      this.cells.insertNextCell(cellPointIds);
    }
  }

  getPolyData() {
    this.createPointData();
    this.createCellData();
    this.polyData.setPoints(this.points);
    this.polyData.setPolys(this.cells);
    this.offsetForBetterView();
  }

  parseForGy(data: any) {
    data.forEach((element: any) => {
      const rest = element.slice(4);
      const cell: TCell = {
        cellId: element[0],
        partId: element[1],
        partType: element[2],
        componentsNumber: element[3],
        nodes: [...rest],
      };
      this.data.push(cell);
    });
    this.getPolyData();
  }

  containsCellId(cellId: number) {
    return cellId < this.cells.getNumberOfCells();
  }

  getGyCellId(id: number) {
    return this.data[id].cellId;
  }

  // 计算网格中心点
  getCellPos(cellId: number): Vector3 {
    const num = this.data[cellId].componentsNumber;
    const pos = [0, 0, 0];
    for (let n = 0; n < num; n++) {
      pos[0] += this.data[cellId].nodes[n][1];
      pos[1] += this.data[cellId].nodes[n][2];
      pos[2] += this.data[cellId].nodes[n][3];
    }
    for (let i = 0; i < pos.length; i++) {
      pos[i] /= num;
    }
    const posV = new Vector3(pos[0], pos[1], pos[2]);
    return posV;
  }

  // * 偏置一个距离来更好的显示
  offsetForBetterView(offset = 0.1) {
    const numPoints = this.points.getNumberOfPoints();
    const normalsFilter = createPolyDataNormals();
    normalsFilter.setComputePointNormals(true);
    normalsFilter.setInputData(this.polyData);
    normalsFilter.update();
    // 获取法向量
    const outputPolyData = normalsFilter.getOutputData();
    const normals = outputPolyData.getPointData().getNormals();
    for (let i = 0; i < numPoints; i++) {
      const point = this.points.getPoint(i);
      const n = normals.getTuple(i);
      const v = offsetByVec3(
        new Vector3(point[0], point[1], point[2]),
        new Vector3(n[0], n[1], n[2]),
        offset
      );
      this.points.setPoint(i, v.x, v.y, v.z);
    }
    this.polyData.modified();
  }
  getCellsFromFaceData(cellId: number) {
    return this.data.find((cell) => cellId === cell.cellId);
  }
}
